package io.gitee.bowen_lee.netty.bowen.server;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.util.CharsetUtil;

// @Sharable // 不加@Sharable报错: io.netty.channel.ChannelPipelineException:
// io.gitee.bowen_lee.netty.client.MyChannelHandle is not a @Sharable handler,
// so can't be added or removed multiple times.
// 因为重复注册了. 或者可以每个线程new一下
public abstract class BowenAcceptChannelHandle extends ChannelInboundHandlerAdapter {

  private NioEventLoopGroup selector;

  private ChannelHandler rwChannelHandle;

  /**
   * 构造
   * 
   * @param eventLoop 事件循环 (就是selector)
   */
  public BowenAcceptChannelHandle(NioEventLoopGroup eventLoop) {
    this.selector = eventLoop;
  }

  /**
   * 构造。 使用
   * 
   * @param eventLoop
   * @param rwChannelHandle
   */
  public BowenAcceptChannelHandle(NioEventLoopGroup eventLoop, ChannelHandler rwChannelHandle) {
    this.selector = eventLoop;
    this.rwChannelHandle = rwChannelHandle;
  }

  /**
   * 构造
   * 
   */
  public BowenAcceptChannelHandle() {
  }

  @Override
  public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
    // 处理 accept
    if (msg instanceof SocketChannel) {
      // listen socket accept
      SocketChannel channel = (SocketChannel) msg; // 已经是执行过 accept的 了.

      // 注册 通道到selcetor
      selector.register(channel);

      // 创建管道
      ChannelPipeline channelPipeline = channel.pipeline();

      // 把 通道处理器 添加到 通道管道中
      // 这个地方是复用了 this 。可以单独创建 channelHandle 处理 读写，类似MyChannelHandle这样
      channelPipeline.addLast(rwChannelHandle);
      // 使用桥梁的方案，去掉 @Sharable
      // channelPipeline.addLast(rwChannelHandle);
    }
    // 处理读写
    // 如果使用 桥梁方法 这个代码可以注释掉
    if (msg instanceof ByteBuf) {
      ByteBuf buf = (ByteBuf) msg;
      // read 方法会动指针
      // CharSequence charSequence = buf.readCharSequence(buf.readableBytes(),
      // CharsetUtil.UTF_8);

      // get 不会动指针
      CharSequence charSequence = buf.getCharSequence(0, buf.readableBytes(),
          CharsetUtil.UTF_8);
      System.out.println("收到" + charSequence.toString());
      println(ctx, charSequence.toString());// 发送内容
    }
  }

  /**
   * 发送啥啊
   * 使用桥梁方法的话。这个代码注释掉
   */
  public abstract void println(ChannelHandlerContext ctx, String msgStr);
}
